package io.jboot.fly.service.impl;

import com.jfinal.kit.Ret;
import com.jfinal.plugin.activerecord.Db;
import com.jfinal.plugin.activerecord.IAtom;
import com.jfinal.plugin.activerecord.Page;
import io.jboot.aop.annotation.Bean;
import io.jboot.db.model.Columns;
import io.jboot.fly.FlyConfig;
import io.jboot.fly.model.Post;
import io.jboot.fly.model.User;
import io.jboot.fly.model.UserAction;
import io.jboot.fly.service.PostService;
import io.jboot.fly.service.UserActionService;
import io.jboot.fly.service.UserService;
import io.jboot.service.JbootServiceBase;
import org.joda.time.DateTime;

import javax.inject.Inject;
import javax.inject.Singleton;
import java.sql.SQLException;
import java.util.Date;
import java.util.List;

@Bean
@Singleton
public class PostServiceImpl extends JbootServiceBase<Post> implements PostService {

    @Override
    public List<Post> findHotPostforUpload() {
        Columns columns = Columns.create().ne("userAttachment_id","null").ge("status", 0).ge("created", DateTime.now().minusDays(30).toDate());
        return DAO.findListByColumns(columns, "view_count desc", 10);
    }



    @Inject
    UserService userService;

    @Inject
    UserActionService userActionService;

    @Override
    public List<Post> findByLevel(int level) {
        Columns columns = Columns.create("level", level).ge("status", 0);
        return DAO.findListByColumns(columns, "created desc");
    }

    @Override
    public List<Post> findByLevelAndCategoryId(int level, String categoryId) {
        Columns columns = Columns.create("category_id", categoryId).eq("level", level).ge("status", 0);
        return DAO.findListByColumns(columns, "created desc");
    }

    @Override
    public List<Post> findHotPosts() {
        Columns columns = Columns.create().ge("status", 0).ge("created", DateTime.now().minusDays(30).toDate());
        return DAO.findListByColumns(columns, "comment_count desc", 10);
    }

    @Override
    public List<Post> dailyQuestion(String id) {
        Columns columns = Columns.create().ge("status", 0).eq("category_id","0c275ece74fe4c1fbcaa9d3c7438f1f3");
        if(id!=null){
            columns.ne("user_id",id);
        }
        return DAO.findListByColumns(columns, "price desc", 5);
    }



    @Override
    public List<Post> findLatestAnnouncement() {
        Columns columns = Columns.create().ge("status", 0).eq("category_id","bb21e00b41174683bd4e5ec2baa88032");
        return DAO.findListByColumns(columns, "created desc", 2);
    }



    @Override
    public List<Post> findByUserIdAndCreated(String userId, Date created) {
        Columns columns = Columns.create("user_id", userId).ge("status", 0).ge("created", created);
        return DAO.findListByColumns(columns, "created desc");
    }

    @Override
    public Page<Post> paginate(int pageNumber, int pageSize, Integer status, Boolean recommend) {
        Columns columns = Columns.create();

        if (status != null) {
            columns.eq("status", status);
        } else {
            columns.ge("status", 0);
        }

        if (recommend != null) {
            columns.eq("recommend", recommend ? 1 : 0);
        }

        return DAO.paginateByColumns(pageNumber, pageSize, columns.getList(), "created desc");
    }

    @Override
    public Page<Post> paginateByParams(int pageNumber, int pageSize, Integer status, Boolean recommend, Columns columns,String orderStr) {
//        Columns columns = Columns.create();

        if (status != null) {
            columns.eq("status", status);
        } else {
            columns.ge("status", 0);
        }

        if (recommend != null) {
            columns.eq("recommend", recommend ? 1 : 0);
        }


        return DAO.paginateByColumns(pageNumber, pageSize, columns.getList(), orderStr);
    }


    @Override
    public Page<Post> paginateByCategoryId(int pageNumber, int pageSize, String categoryId, Integer status, Boolean recommend) {
        Columns columns = Columns.create("category_id", categoryId);

        if (status != null) {
            columns.eq("status", status);
        } else {
            columns.ge("status", 0);
        }

        if (recommend != null) {
            columns.eq("recommend", recommend ? 1 : 0);
        }

        return DAO.paginateByColumns(pageNumber, pageSize, columns.getList(), "created desc");
    }

    @Override
    public Page<Post> paginateByUserId(int pageNumber, int pageSize, String userId) {
        Columns columns = Columns.create("user_id", userId);
        return DAO.paginateByColumns(pageNumber, pageSize, columns.getList(), "created desc");
    }

    @Override
    public Ret doZanPost(String postId, User user) {

        Post post = findById(postId);
        if (post == null) {
            return Ret.fail("message", "ID数据错误");
        }

        //已经结帖了
        if (post.isFinished()) {
            return Ret.fail("message", "已经结帖了");
        }

        //判断是否已被点赞或鄙视
        List<UserAction> actionZan_post = userActionService.findByUserIdPostIdAction(user.getId(), postId, UserAction.ACTION_POST_ZAN);
        List<UserAction> actionDespise_post = userActionService.findByUserIdPostIdAction(user.getId(), postId, UserAction.ACTION_POST_DESPISED);
        String status_zan_or_despise = null;
        if (actionZan_post.isEmpty() && actionDespise_post.isEmpty()) {
            status_zan_or_despise = Post.STATUS_NO_ZAN_NO_DESPISE;
        } else if (!actionZan_post.isEmpty() && actionDespise_post.isEmpty()) {
            status_zan_or_despise = Post.STATUS_ZAN_NO_DESPISE;
        } else if (actionZan_post.isEmpty() && !actionDespise_post.isEmpty()) {
            status_zan_or_despise = Post.STATUS_NO_ZAN_DESPISE;
        }
        boolean success = Db.tx(new IAtom() {
            @Override
            public boolean run() throws SQLException {
                int zanPostPoint = FlyConfig.get().getZanPostPoint();
                if (actionZan_post.isEmpty() && actionDespise_post.isEmpty()) {
                    //被点赞发帖人得分（+1）
                    if (!userService.changePoint(post.getUserId(), zanPostPoint)) {
                        return false;
                    }
                    UserAction zanPost = new UserAction();
                    zanPost.setAction(UserAction.ACTION_POST_ZAN);
                    zanPost.setUserId(user.getId());    // 记录评论人
                    zanPost.setPostId(post.getId());
                    zanPost.setPoint(zanPostPoint);
                    if (!userActionService.save(zanPost)) {
                        return false;
                    }
                    //更新被点赞值
                    if (!changeVoteUp(postId, zanPostPoint)) {
                        return false;
                    }
                } else if (!actionZan_post.isEmpty() && actionDespise_post.isEmpty()) {
                    //已点赞要取消 评论人减分
                    if (!userService.changePoint(post.getUserId(), (-zanPostPoint))) {
                        return false;
                    }
                    UserAction zanPost = new UserAction();
                    zanPost.setAction(UserAction.ACTION_POST_ZAN_CONSOLE);
                    zanPost.setUserId(user.getId());
                    zanPost.setPostId(post.getId());
                    zanPost.setPoint(zanPostPoint);
                    if (!userActionService.save(zanPost)) {
                        return false;
                    }
                    //更新被点赞值
                    if (!changeVoteUp(postId, (-zanPostPoint))) {
                        return false;
                    }
                    //删掉点赞记录
                    if (!userActionService.deleteByUserIdPostIdAction(user.getId(), postId, UserAction.ACTION_POST_ZAN)) {
                        return false;
                    }
                } else if (actionZan_post.isEmpty() && !actionDespise_post.isEmpty()) {
                    //由鄙视转为点赞
                    if (!userService.changePoint(post.getUserId(), (2*zanPostPoint))) {
                        return false;
                    }
                    UserAction zanPost = new UserAction();
                    zanPost.setAction(UserAction.ACTION_POST_DESPISED_TO_ZAN);
                    zanPost.setUserId(user.getId());
                    zanPost.setPostId(post.getId());
                    zanPost.setPoint(2*zanPostPoint);
                    if (!userActionService.save(zanPost)) {
                        return false;
                    }
                    UserAction zanPost_new_despise = new UserAction();
                    zanPost_new_despise.setAction(UserAction.ACTION_POST_ZAN);
                    zanPost_new_despise.setUserId(user.getId());
                    zanPost_new_despise.setPostId(post.getId());
                    zanPost_new_despise.setPoint(zanPostPoint);
                    if (!userActionService.save(zanPost_new_despise)) {
                        return false;
                    }
                    //更新被点赞值
                    if (!changeVoteUp(postId, zanPostPoint)) {
                        return false;
                    }
                    if (!changeVoteDown(postId, (-zanPostPoint))) {
                        return false;
                    }
                    //删掉鄙视记录
                    if (!userActionService.deleteByUserIdPostIdAction(user.getId(), postId, UserAction.ACTION_POST_DESPISED)) {
                        return false;
                    }
                } else {
                    return false;
                }
                return true;
            }
        });

        return success ? Ret.ok().set("status_zan_or_despise", status_zan_or_despise): Ret.fail("message", "系统错误，请稍后再试");



    }

    @Override
    public Ret doDespisePost(String postId, User user) {

        Post post = findById(postId);
        if (post == null) {
            return Ret.fail("message", "ID数据错误");
        }

        //已经结帖了
        if (post.isFinished()) {
            return Ret.fail("message", "已经结帖了");
        }

        //判断是否已被鄙视或点赞
        List<UserAction> actionZan_post = userActionService.findByUserIdPostIdAction(user.getId(), postId, UserAction.ACTION_POST_ZAN);
        List<UserAction> actionDespise_post = userActionService.findByUserIdPostIdAction(user.getId(), postId, UserAction.ACTION_POST_DESPISED);
        String status_zan_or_despise = null;
        if (actionDespise_post.isEmpty() && actionZan_post.isEmpty()) {
            status_zan_or_despise = Post.STATUS_NO_ZAN_NO_DESPISE;
        } else if (!actionDespise_post.isEmpty() && actionZan_post.isEmpty()) {
            status_zan_or_despise = Post.STATUS_NO_ZAN_DESPISE;
        } else if (actionDespise_post.isEmpty() && !actionZan_post.isEmpty()) {
            status_zan_or_despise = Post.STATUS_ZAN_NO_DESPISE ;
        }
        boolean success = Db.tx(new IAtom() {
            @Override
            public boolean run() throws SQLException {
                int despisePostPoint = FlyConfig.get().getDespisePostPoint();
                if (actionDespise_post.isEmpty() && actionZan_post.isEmpty()) {
                    //被鄙视发帖人得分（-1）
                    if (!userService.changePoint(post.getUserId(), (-despisePostPoint))) {
                        return false;
                    }
                    UserAction despisePost = new UserAction();
                    despisePost.setAction(UserAction.ACTION_POST_DESPISED);
                    despisePost.setUserId(user.getId());    // 记录评论人
                    despisePost.setPostId(post.getId());
                    despisePost.setPoint(despisePostPoint);
                    if (!userActionService.save(despisePost)) {
                        return false;
                    }
                    //更新被鄙视值
                    if (!changeVoteDown(postId, despisePostPoint)) {
                        return false;
                    }
                } else if (!actionDespise_post.isEmpty() && actionZan_post.isEmpty()) {
                    //已鄙视要取消 评论人加分
                    if (!userService.changePoint(post.getUserId(), (despisePostPoint))) {
                        return false;
                    }
                    UserAction despisePost = new UserAction();
                    despisePost.setAction(UserAction.ACTION_POST_ZAN_CONSOLE);
                    despisePost.setUserId(user.getId());
                    despisePost.setPostId(post.getId());
                    despisePost.setPoint(despisePostPoint);
                    if (!userActionService.save(despisePost)) {
                        return false;
                    }
                    //更新被鄙视值
                    if (!changeVoteDown(postId, (-despisePostPoint))) {
                        return false;
                    }
                    //删掉鄙视记录
                    if (!userActionService.deleteByUserIdPostIdAction(user.getId(), postId, UserAction.ACTION_POST_DESPISED)) {
                        return false;
                    }
                } else if (actionDespise_post.isEmpty() && !actionZan_post.isEmpty()) {
                    //由点赞转为鄙视
                    if (!userService.changePoint(post.getUserId(), (-2*despisePostPoint))) {
                        return false;
                    }
                    UserAction despisePost = new UserAction();
                    despisePost.setAction(UserAction.ACTION_POST_ZAN_TO_DESPISED);
                    despisePost.setUserId(user.getId());
                    despisePost.setPostId(post.getId());
                    despisePost.setPoint(2*despisePostPoint);
                    if (!userActionService.save(despisePost)) {
                        return false;
                    }
                    UserAction despisePost_new_despise = new UserAction();
                    despisePost_new_despise.setAction(UserAction.ACTION_POST_DESPISED);
                    despisePost_new_despise.setUserId(user.getId());
                    despisePost_new_despise.setPostId(post.getId());
                    despisePost_new_despise.setPoint(despisePostPoint);
                    if (!userActionService.save(despisePost_new_despise)) {
                        return false;
                    }
                    //更新被点赞值
                    if (!changeVoteUp(postId, (-despisePostPoint))) {
                        return false;
                    }
                    if (!changeVoteDown(postId, despisePostPoint)) {
                        return false;
                    }
                    //删掉点赞记录
                    if (!userActionService.deleteByUserIdPostIdAction(user.getId(), postId, UserAction.ACTION_POST_ZAN)) {
                        return false;
                    }
                } else {
                    return false;
                }
                return true;
            }
        });

        return success ? Ret.ok().set("status_zan_or_despise", status_zan_or_despise): Ret.fail("message", "系统错误，请稍后再试");
    }


    /**
     * 保存 帖子
     * <p>
     * 有三个逻辑：
     * 1、扣除用于的悬赏积分
     * 2、增加 用户发布帖子 的奖励积分
     * 3、生成 UserAction 记录用户 奖励信息
     *
     * @param post
     * @return
     */
    @Override
    public boolean save(Post post) {
        return Db.tx(new IAtom() {
            @Override
            public boolean run() throws SQLException {
                if (!post.save()) {
                    return false;
                }

                if (!userService.changePoint(post.getUserId(), -post.getPayPoint())) {
                    return false;
                }

                int newPostPoint = FlyConfig.get().getNewPostPoint();
                if (!userService.changePoint(post.getUserId(), newPostPoint)) {
                    return false;
                }

                UserAction userAction = new UserAction();
                userAction.setAction(UserAction.ACTION_NEW_POST);
                userAction.setUserId(post.getUserId());
                userAction.setPostId(post.getId());
                userAction.setPoint(newPostPoint);

                if (!userActionService.save(userAction)) {
                    return false;
                }

                return true;
            }
        });
    }

    public boolean changeVoteUp(String postId, int point) {
        String sql = "update `post` SET vote_up = vote_up + ? where id = ? ";
        return Db.update(sql, point, postId) > 0;
    }

    public boolean changeVoteDown(String postId, int point) {
        String sql = "update `post` SET vote_down = vote_down + ? where id = ? ";
        return Db.update(sql, point, postId) > 0;
    }

    @Override
    public int getPostForUploadCount(String userId) {

        return Db.queryInt("select count(*) from `post` where user_id = ? and userAttachment_id !=null",userId);
    }


}